package com.able.concurrency.t2;

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author abel.he
 * @data 2018/8/18 14:59
 * @describe
 */
public class Test6<E> {

    LinkedList<E> linkedList = new LinkedList<E>();

    Lock lock = new ReentrantLock();
    Condition sort1 = lock.newCondition();
    Condition sort2 = lock.newCondition();
    Condition sort3 = lock.newCondition();

    void m1() {
        try {
            lock.lock();
            // 10 7 4 1 m1()
//            boolean flag = ;
//            System.out.println("进入 m1(） 方法  " + flag);
            while (linkedList.size() != 10 && linkedList.size() != 7 && linkedList.size() != 4 && linkedList.size() != 1 && linkedList.size() != 0) {
                try {
//                    System.out.println("sort1 加锁  集合数量： " + linkedList.size());
                    sort1.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + " m1() count:" + linkedList.size());
            if (linkedList.size() > 0) {
                linkedList.removeFirst();
            }

//            System.out.println("sort2 释放锁");
            sort2.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    void m2() {
        try {
            lock.lock();
            // 9 6 3
//            boolean flag = linkedList.size() != 9 && linkedList.size() != 6 && linkedList.size() != 3;
            while (linkedList.size() != 9 && linkedList.size() != 6 && linkedList.size() != 3 && linkedList.size() != 0) {
                try {
//                    System.out.println("sort2 加锁  集合数量： " + linkedList.size());
                    sort2.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + " m2() count:" + linkedList.size());
            if (linkedList.size() > 0) {
                linkedList.removeFirst();
            }

//            System.out.println("sort3 释放锁");
            sort3.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    void m3() {
        try {
            lock.lock();
            // 8 5 2
//            boolean flag = linkedList.size() != 8 && linkedList.size() != 5 && linkedList.size() != 2;
            while (linkedList.size() != 8 && linkedList.size() != 5 && linkedList.size() != 2 && linkedList.size() != 0) {
                try {
//                    System.out.println("sort3 加锁  集合数量： " + linkedList.size());
                    sort3.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + " m3() count:" + linkedList.size());
            if (linkedList.size() > 0) {
                linkedList.removeFirst();
            }
//            System.out.println("sort1 释放锁");
            sort1.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        final Test6<Integer> test6 = new Test6<Integer>();
        for (int i = 0; i < 10; i++) {
            test6.linkedList.add(i);
        }

        new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 5; i++) {
                    test6.m1();
                }
            }
        }).start();

        TimeUnit.SECONDS.sleep(1);

        new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 5; i++) {
                    test6.m2();
                }
            }
        }).start();

        TimeUnit.SECONDS.sleep(1);

        new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 5; i++) {
                    test6.m3();
                }
            }
        }).start();

//        for (int i = 0; i < 5; i++) {
//            new Thread(new Runnable() {
//                public void run() {
//                    test6.m1();
//                }
//            }).start();
//        }
//
//        TimeUnit.SECONDS.sleep(1);
//
//        for (int i = 0; i < 5; i++) {
//            new Thread(new Runnable() {
//                public void run() {
//                    test6.m2();
//                }
//            }).start();
//        }
//
//        TimeUnit.SECONDS.sleep(1);
//
//        for (int i = 0; i < 5; i++) {
//            new Thread(new Runnable() {
//                public void run() {
//                    test6.m3();
//                }
//            }).start();
//        }
    }

}
